package com.gxa.pingan.controller;

import com.gxa.pingan.common.ExceptionCode;
import com.gxa.pingan.common.JsonResult;
import com.gxa.pingan.exception.BusinessException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * ControllerAdvice本质上就是一个aop的通知,专门用于加强异常出现的时候的抛出通知
 * @author YXQ
 * @date 2021/10/21 20:32
 */
@RestController
@ControllerAdvice
public class ExceptionController {
    /**
     * 当有异常发生,抛出通知介入到目标操作
     * 并把异常对象注入到参数Exception中
     * value表示什么类型的错误或异常才会被记录
     * 我们选择使用Throwable.class(Error和Exception都记录)
     */
    @ExceptionHandler(value = {Throwable.class})
    public Map<String, Object> handler(Exception e, HttpServletResponse response, HttpServletRequest request) throws IOException {
        JsonResult jsonResult = new JsonResult();
        if (e instanceof BusinessException){
            // 业务异常
            // 暂时打印在控制台
            e.printStackTrace();
            // 错误码
            jsonResult.setCode(""+((BusinessException) e).getExceptionCode().getCode());
            // 错误信息
            jsonResult.setMsg(((BusinessException) e).getExceptionCode().getMessage());
            return jsonResult.getDataMap();
        }else{
            // 暂时打印在控制台
            e.printStackTrace();
            // 系统异常处理--记录日志，追加到文件中
            String realPath = request.getServletContext().getRealPath("/");
            // 获取日期并格式化，最终加到文件名中
            String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            // 拼接文件名
            File file = new File(realPath+"/"+format+"error.log");
            if (!file.exists()){
                // 如果文件不存在，创建文件
                boolean newFile = file.createNewFile();
            }
            // 文件字符输出流
            FileOutputStream fileOutputStream = new FileOutputStream(file,true);
            // 包装流，并设置字符集
            OutputStreamWriter writer = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
            // 写入的内容格式:
            /* ---------
             异常的类型
             异常的原因
             异常在栈中的轨迹
             ---------*/
            // 拼接异常字符串
            StringBuilder stringBuilder = new StringBuilder("");
            stringBuilder.append("───────────────────────────────────────────────────────").append("\n");
            stringBuilder.append("异常时间:  ").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("\n");
            stringBuilder.append("异常的类型:").append(e.toString()).append("\n");
            stringBuilder.append("异常的原因:").append(e.getMessage()).append("\n");
            stringBuilder.append("异常在栈中的轨迹:").append("\n");
            StackTraceElement[] stackTrace = e.getStackTrace();
            for (StackTraceElement stackTraceElement : stackTrace) {
                stringBuilder.append(stackTraceElement).append("\n");
            }
            stringBuilder.append("───────────────────────────────────────────────────────").append("\n");
            // 将异常信息打印到文件中
            writer.write(stringBuilder.toString());
            // 刷新缓冲
            writer.flush();
            // 关闭输出流
            writer.close();
            // 给前端的反馈
            jsonResult.setCode("" + ExceptionCode.SERVICE_ERROR.getCode());
            jsonResult.setMsg(ExceptionCode.SERVICE_ERROR.getMessage());
            return jsonResult.getDataMap();
        }
    }

}
